﻿#region Creditos

/* Autor: Edilberto Sánchez Forero	*/
/* Email: esanchezfo@gmail.com		*/
/* Licencia: LGPL, Software Libre	*/
/* País: Colombia, Bogotá			*/

#endregion

#region Librerias

using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System;
using ESF.General.Entity;
using ESF.General;
using System.Collections.Generic;

#endregion


namespace ESF.Web.ServerControls
{
	[AspNetHostingPermission(SecurityAction.Demand,
        Level = AspNetHostingPermissionLevel.Minimal),
    AspNetHostingPermission(SecurityAction.InheritanceDemand, 
        Level = AspNetHostingPermissionLevel.Minimal),
	ToolboxData("<{0}:DataPagging runat=\"server\"></{0}:DataPagging>")]
	public class DataPagging : WebControl, INamingContainer
	{
		#region Delegados
		
		public delegate void PageChanged ();
				
		public event PageChanged OnPageChanged;

		public delegate void Clear();

		public event Clear DoClear;

		public delegate void SelectAllInPage();

		public event SelectAllInPage DoSelectAllInPage;

		#endregion
		
		
		#region Miembros
		
		private Button imgPrevious;
		private Button imgNext;
		private Button imgFirst;
		private Button imgLast;

		private Button btnClear;
		private Button btnSelectAllInPage;
				
		private DropDownList ddlPageSize;
		private DropDownList ddlPageIndex;
		
		private PaggingInfo _PaggingInfo;
		

		private bool _ReportOnChange = true;

		#endregion
		
		
		#region Propiedades
		
		public string MasterDataPaggingControlID
		{
			set
			{
				ViewState ["MasterDataPaggingControlID"] = value;
			}
			get
			{
				return ViewState ["MasterDataPaggingControlID"] as string;
			}
		}

		public override bool Visible
		{
			get
			{
				return base.Visible;
			}
			set
			{
				EnsureChildControls();

				base.Visible = value;

				// es un maestro
				if (string.IsNullOrEmpty(MasterDataPaggingControlID))
				{
					//if (!value)
					//{
						NotifyVisibleReplicators(value);
					//}
					//else
					//{
					//    // esta vacio no se muestran sus hijos
					//    if (PaggingInfo.RowCount == 0)
					//    {
					//        NotifyVisibleReplicators(false);
					//    } 
					//    else
					//    {
					//        NotifyVisibleReplicators(true);
					//    }						
					//}
				}
			}
		}


		public bool ShowPageSize
		{
			set
			{
				ViewState ["ShowPageSize"] = value;
			}
			get
			{
				if (ViewState ["ShowPageSize"] == null) { return true; }

				return (bool) ViewState ["ShowPageSize"];
			}
		}

		
		private int DefaultPageSize
		{
			get
			{
				if (ViewState["DefaultPageSize"] == null)
				{
					return PaggingInfo.DEFAULT_PAGESIZE;
				}

				return (int) ViewState["DefaultPageSize"];
			}
		}
		
		
		public int PageSize
		{
			set 
			{
				if (ViewState["DefaultPageSize"] == null)
				{
					ViewState["DefaultPageSize"] = value;
				}
				
				ViewState ["PageSize"] = value;
			}
			get 
			{
				if (ViewState ["PageSize"] == null)
				{
					return PaggingInfo.DEFAULT_PAGESIZE;
				}

				return (int) ViewState["PageSize"];
			}
		}


		public int PageIndexNoChanges
		{
			set
			{
				_ReportOnChange = false;

				PageIndex = value;

				ChangeToDefaultPageSize ();
			}
		}


		public bool IsVisibleSelectAllInPage
		{
			set
			{
				EnsureChildControls ();

				btnSelectAllInPage.Visible = value;
			}
		}


		public bool IsVisibleClear
		{
			set
			{
				EnsureChildControls();

				btnClear.Visible = value;
			}
		}

		
		public int PageIndex
		{
			set 
			{
				ViewState ["PageIndex"] = value;

				// si es un maestro
				NotifyReplicators (); 

				if (_ReportOnChange)
				{
					CallOnPageChanged ();
				}
			}
			get 
			{
				if (ViewState ["PageIndex"] == null)
				{
					return 0;
				}

				return Convert.ToInt32 (ViewState ["PageIndex"]);
			}
		}
		
		
		private int RowCount
		{
			set { ViewState ["RowCount"] = value; }
			get { return Convert.ToInt32 (ViewState ["RowCount"]); }
		}
		
		
		public PaggingInfo PaggingInfo
		{
			get 
			{
				return new PaggingInfo () { PageIndex = PageIndex, PageSize = PageSize, RowCount = RowCount };
			}
			set
			{
				EnsureChildControls ();
				
				// es un esclavo y esta vacio no se muestra
				if (!string.IsNullOrEmpty (MasterDataPaggingControlID) && value.RowCount == 0)
				{
					Visible = false;
				}

				// Solo si hay cambio
				if (!PaggingInfo.Equals (value))
				{
					RowCount = value.RowCount;
					PageSize = value.PageSize;

					PageIndex = value.PageIndex;

					ListLoader.LoadListRange(ddlPageIndex, 1, value.PageCount);
					ListLoader.RemoveSelectItem(ddlPageIndex);
				
					ddlPageIndex.Enabled = (PaggingInfo.PageCount > 1);
				}
			}
		}


		public PaggingInfo PaggingInfoNoChanges
		{
			set
			{
				_ReportOnChange = false;

				PaggingInfo = value;
			}
		}


		public string ReplicatePaggingControlIDs
		{
			set
			{
				ViewState ["ReplicatePaggingControlIDs"] = value;
			}
			get
			{
				return ViewState ["ReplicatePaggingControlIDs"] as string;
			}
		}

		#endregion
		
		
		#region Inicializar

		public void ChangeToDefaultPageSize ()
		{
			PageSize = DefaultPageSize;
		}


		protected override void CreateChildControls()
		{
			ddlPageSize = new DropDownList ();
			ddlPageSize.ID = "ddlPageSize";
			
			ListLoader.LoadListPageSize(ddlPageSize);
			
			ddlPageSize.AutoPostBack = true;
			ddlPageSize.SelectedIndexChanged += ddlPageSize_SelectedIndexChanged;

			
			ddlPageIndex = new DropDownList ();
			ddlPageIndex.ID = "ddlPageIndex";
			ddlPageIndex.AutoPostBack = true;
			ddlPageIndex.SelectedIndexChanged += ddlPageIndex_SelectedIndexChanged;			

			imgFirst = new Button ();
			imgFirst.CausesValidation = false;
			imgFirst.UseSubmitBehavior = false; 
			imgFirst.ID = "imgFirst";
			imgFirst.CssClass="imgFirst imgBtnLeft";
			imgFirst.Text = "Primero";
			imgFirst.CausesValidation = false;
			imgFirst.Click += imgFirst_Click;
			
			imgLast = new Button ();
			imgLast.CausesValidation = false;
			imgLast.UseSubmitBehavior = false; 
			imgLast.ID = "imgLast";
			imgLast.CssClass = "imgLast imgBtnRight";
			imgLast.Text = "Último";
			imgLast.CausesValidation = false;
			imgLast.Click += imgLast_Click;
			
			imgNext = new Button ();
			imgNext.CausesValidation = false;
			imgNext.UseSubmitBehavior = false; 
			imgNext.ID = "imgNext";
			imgNext.CssClass = "imgNext imgBtnRight";
			imgNext.Text = "Siguiente";
			imgNext.CausesValidation = false;
			imgNext.Click += imgNext_Click;
			
			imgPrevious = new Button ();
			imgPrevious.CausesValidation = false;
			imgPrevious.UseSubmitBehavior = false; 
			imgPrevious.ID = "imgPrevious";
			imgPrevious.CssClass = "imgPrevious imgBtnLeft";
			imgPrevious.Text = "Anterior";
			imgPrevious.CausesValidation = false;
			imgPrevious.Click += imgPrevious_Click;
			
			btnClear = new Button ();
			btnClear.ID = "btnClear";
			btnClear.ToolTip = "Al dar click limpiara los campos de filtro y los resultados";
			btnClear.CssClass = "btnClear";
			btnClear.Text = "Limpiar";
			btnClear.Click += btnClear_Click;
			btnClear.Visible = false;
			btnClear.CausesValidation = false;
			btnClear.UseSubmitBehavior = false;

			btnSelectAllInPage = new Button ();
			btnSelectAllInPage.ID = "btnSelectAllInPage";
			btnSelectAllInPage.CausesValidation = false;
			btnSelectAllInPage.UseSubmitBehavior = false;
			btnSelectAllInPage.CssClass = "btnSelectAllInPage";
			btnSelectAllInPage.ToolTip = "Marca como seleccionados solo los elementos mostrados en esta página de resultados (no todos)";
			btnSelectAllInPage.Text = "Seleccione Estos";
			btnSelectAllInPage.Click += btnSelectAllInPage_Click;
			btnSelectAllInPage.Visible = false;

			Controls.Add (btnClear);
			Controls.Add (btnSelectAllInPage);
			Controls.Add (imgFirst);
			Controls.Add (imgNext);
			Controls.Add (imgPrevious);
			Controls.Add (imgLast);
			Controls.Add (ddlPageSize);
			Controls.Add (ddlPageIndex);
		}


		private void NotifyReplicators ()
		{
			string replicatorControlIDs;

			DataPagging control;

			PaggingInfo pagInfo;


			replicatorControlIDs = ReplicatePaggingControlIDs;

			if (string.IsNullOrEmpty (replicatorControlIDs))
			{
				return;
			}

			pagInfo = PaggingInfo;

			foreach (string controlID in replicatorControlIDs.Split (','))
			{
				if (controlID == ID)
				{
					continue;
				}

				control = Parent.FindControlRecursiveParent<DataPagging>(controlID.Trim());

				if (control == null)
				{
					throw new Exception (string.Format ("The control with ID \"{0}\" must be a DataPagging in order to replicate pagging changes", controlID.Trim ()));
				}

				control.PaggingInfo = pagInfo;
				control.Visible = Visible;
			}
		}


		private void NotifyVisibleReplicators (bool pVisible)
		{
			string replicatorControlIDs;

			DataPagging control;


			replicatorControlIDs = ReplicatePaggingControlIDs;

			if (string.IsNullOrEmpty(replicatorControlIDs))
			{
				return;
			}

			foreach (string controlID in replicatorControlIDs.Split(','))
			{
				if (controlID == ID)
				{
					continue;
				}

				control = Parent.FindControlRecursiveParent<DataPagging>(controlID.Trim());

				if (control == null)
				{
					throw new Exception(string.Format("The control with ID \"{0}\" must be a DataPagging in order to replicate pagging changes", controlID.Trim()));
				}

				control.Visible = pVisible;
			}
		}

		#endregion
		
		
		#region Render

		protected override void OnPreRender(EventArgs e)
		{
			HttpContext.Current.Trace.Write ("DataPagging.OnPreRender Start");

			ListLoader.Select (ddlPageSize, PageSize);
			ListLoader.Select(ddlPageIndex, PageIndex + 1);

			HttpContext.Current.Trace.Write("DataPagging.OnPreRender End");
		}


		protected override void Render (HtmlTextWriter pWriter)
		{
			HttpContext.Current.Trace.Write("DataPagging.Render Start");

			_PaggingInfo = PaggingInfo;

			pWriter.AddAttribute(HtmlTextWriterAttribute.Class, (string.IsNullOrEmpty (CssClass) ? "divPager" : CssClass));
				pWriter.AddAttribute(HtmlTextWriterAttribute.Id, ClientID);
			pWriter.RenderBeginTag(HtmlTextWriterTag.Div);

					if (_PaggingInfo.RowCount == 0)
					{
							pWriter.AddAttribute(HtmlTextWriterAttribute.Class, "pagerEmptyMessage");
						pWriter.RenderBeginTag(HtmlTextWriterTag.Div);

							pWriter.Write ("No fueron registros encontrados");

						pWriter.RenderEndTag ();
					}				
					else
					{
						#region Back Buttons

							pWriter.AddAttribute(HtmlTextWriterAttribute.Class, "containerLeft");
						pWriter.RenderBeginTag(HtmlTextWriterTag.Div);

							if (_PaggingInfo.IsThereFirst)
							{
								imgFirst.RenderControl (pWriter);
							}

							if (_PaggingInfo.IsTherePrevious)
							{
								imgPrevious.RenderControl(pWriter);
							}

						pWriter.RenderEndTag ();
					
						#endregion

						#region Info

							pWriter.AddAttribute(HtmlTextWriterAttribute.Class, "contents");
						pWriter.RenderBeginTag(HtmlTextWriterTag.Div);

								pWriter.AddAttribute (HtmlTextWriterAttribute.Class, "info");
							pWriter.RenderBeginTag (HtmlTextWriterTag.Div);

									pWriter.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "0");
									pWriter.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "0");
									pWriter.AddAttribute(HtmlTextWriterAttribute.Align, "center");
								pWriter.RenderBeginTag(HtmlTextWriterTag.Table);

									pWriter.RenderBeginTag(HtmlTextWriterTag.Tr);

										pWriter.RenderBeginTag(HtmlTextWriterTag.Td);
											btnClear.RenderControl (pWriter);
										pWriter.RenderEndTag();

										pWriter.RenderBeginTag(HtmlTextWriterTag.Td);
											btnSelectAllInPage.RenderControl(pWriter);
										pWriter.RenderEndTag();

										pWriter.RenderBeginTag(HtmlTextWriterTag.Td);
											pWriter.Write ("Pág.");
										pWriter.RenderEndTag ();
														
										pWriter.RenderBeginTag(HtmlTextWriterTag.Td);

											ddlPageIndex.RenderControl (pWriter);
						
										pWriter.RenderEndTag ();

										pWriter.RenderBeginTag(HtmlTextWriterTag.Td);
											pWriter.Write("de");
										pWriter.RenderEndTag();

											pWriter.AddAttribute(HtmlTextWriterAttribute.Class, "pageCount");
										pWriter.RenderBeginTag(HtmlTextWriterTag.Td);
											pWriter.Write(_PaggingInfo.PageCount);
										pWriter.RenderEndTag();

										pWriter.RenderBeginTag(HtmlTextWriterTag.Td);
											pWriter.Write("para");	
										pWriter.RenderEndTag();

											pWriter.AddAttribute(HtmlTextWriterAttribute.Class, "rowCount");
										pWriter.RenderBeginTag(HtmlTextWriterTag.Td);
										pWriter.Write(_PaggingInfo.RowCount);
										pWriter.RenderEndTag();

										if (ShowPageSize)
										{
											pWriter.RenderBeginTag(HtmlTextWriterTag.Td);
												pWriter.Write ("Ver: ");
											pWriter.RenderEndTag ();
									
											pWriter.RenderBeginTag(HtmlTextWriterTag.Td);

													ddlPageSize.Enabled = ddlPageIndex.Enabled;
													ddlPageSize.RenderControl (pWriter);

											pWriter.RenderEndTag ();
										}

									pWriter.RenderEndTag();

								pWriter.RenderEndTag ();	

							pWriter.RenderEndTag();

						pWriter.RenderEndTag();
					
					#endregion

						#region Forward Buttons

							pWriter.AddAttribute(HtmlTextWriterAttribute.Class, "containerRight");
						pWriter.RenderBeginTag(HtmlTextWriterTag.Div);

							if (_PaggingInfo.IsThereLast)
							{
								imgLast.RenderControl(pWriter);
							}

							if (_PaggingInfo.IsThereNext)
							{
								imgNext.RenderControl(pWriter);
							}

						pWriter.RenderEndTag ();

						#endregion
					}

			pWriter.RenderEndTag ();

			HttpContext.Current.Trace.Write("DataPagging.Render End");
		}
		
		#endregion
		
		
		#region Miembros de IPostBackEventHandler

		public void ddlPageIndex_SelectedIndexChanged(object sender, EventArgs e)
		{
			_ReportOnChange = true;

			PageIndex = int.Parse (ddlPageIndex.SelectedValue) - 1;

			Page.Trace.Write(string.Format("Changed => PageIndex: {0}, PageSize: {1}, RowCount: {2}", PageIndex, PageSize, RowCount));
		}


		public void ddlPageSize_SelectedIndexChanged(object sender, EventArgs e)
		{
			Page.Trace.Write(string.Format("Changed => PageIndex: {0}, PageSize: {1}, RowCount: {2}", PageIndex, PageSize, RowCount));

			PageSize = TextHelper.GetInt(ddlPageSize.SelectedValue, PaggingInfo.DEFAULT_PAGESIZE);

			_ReportOnChange = true;

			PageIndex = 0;
		}

		
		public void btnClear_Click(object sender, EventArgs e)
		{
			if (DoClear != null)
			{
				DoClear ();
			}
		}


		public void btnSelectAllInPage_Click(object sender, EventArgs e)
		{
			if (DoSelectAllInPage != null)
			{
				DoSelectAllInPage ();

				Visible = true;
			}
		}


		public void imgFirst_Click(object sender, EventArgs e)
		{
			ChangePageIndex ("First");
		}


		public void imgLast_Click(object sender, EventArgs e)
		{
			ChangePageIndex ("Last");
		}


		public void imgPrevious_Click(object sender, EventArgs e)
		{
			ChangePageIndex ("Previous");
		}


		public void imgNext_Click(object sender, EventArgs e)
		{
			ChangePageIndex ("Next");
		}

		
		public void ChangePageIndex (string pEventArgument)
		{
			Page.Trace.Write(string.Format("Changed => PageIndex: {0}, PageSize: {1}, RowCount: {2}", PageIndex, PageSize, RowCount));

			_PaggingInfo = new PaggingInfo () { PageIndex = PageIndex, PageSize = PageSize, RowCount = RowCount };
			
			switch (pEventArgument)
			{
				case "Next": _PaggingInfo.SetNext (); break;
				case "Previous": _PaggingInfo.SetPrevious (); break;
				case "First": _PaggingInfo.SetFirst (); break;
				case "Last": _PaggingInfo.SetLast (); break;
			}

			Page.Trace.Write(string.Format("Changed => PageIndex: {0}, PageSize: {1}, RowCount: {2}", PageIndex, PageSize, RowCount));

			_ReportOnChange = true; 
			
			PageIndex = _PaggingInfo.PageIndex;
		}


		/// <summary>
		/// Pone el paginador en su estado de datos por defecto
		/// PageIndex = 0, PageSize = (definido o por defecto)
		/// </summary>
		public void Reset ()
		{
			PageIndexNoChanges = 0;
		}


		public void ShowEmptyMessage ()
		{
			PaggingInfoNoChanges = PaggingInfo.Empty;

			Visible = true;
		}


		public void CallOnPageChanged ()
		{
			DataPagging masterPager;

			PaggingInfo pagInfo;


			pagInfo = PaggingInfo;


			// si no es nulo es un esclavo
			if (!string.IsNullOrEmpty (MasterDataPaggingControlID))
			{
				masterPager = Parent.FindControlRecursiveParent<DataPagging> (MasterDataPaggingControlID);

				if (masterPager == null)
				{
					throw new Exception (string.Format ("The master pager control {0} for {1} was not found", MasterDataPaggingControlID, ID));
				}

				masterPager.PaggingInfo = pagInfo;
			}
			else
			{
				if (OnPageChanged != null)
				{
					OnPageChanged ();
				}
			}
		}
		
		#endregion
	}
}
